#pragma once
#include <mutex>
#include <stdexcept>
#include <unordered_map>
#include <string>
#include <functional>
#include <regex>
#include <unordered_set>
#include <typeinfo>
#include <initializer_list>


/**
 *                                             ***************************
 *                                             *        反射工具类         *
 *                                             ***************************
 *
 *
 *用例：
 *
 *==============================================类定义页====================================================================
 *
 *class A : public ClassReflectionTool::Object<std::string> { //必须继承Object类
 *public:
 *  A() = default;
 *  ~A() = default;
 *  int inumber;
 *
 *  std::string getType()override { //该函数必须需重写
 *      return "A";
 *  }
 *  void test() {
 *      std::cout << "A::test()" << std::endl;
 *  }
 * };
 *
 * 注册类
 *REGISTER_CLASS(A);
 *注册类成员变量
 *REGISTER_CLASS_FIELD(A,inumber,int);
 *注册类成员函数
 *REGISTER_CLASS_METHOD(A,test,void);
 *
 *
 *===================================================使用页===============================================================
 * 获取工厂单例
 * typename ClassReflectionTool::ClassFactory<std::string>* factory =ClassReflectionTool::ClassFactory<std::string>::getSingleton();
 *
 *创建类实例
 *typename ClassReflectionTool::Object<std::string>* obj = factory->createClass("A");
 *
 *设置成员函数
 *std::string fieldName = "inumber";obj->set(fieldName,2);
 *A* a = (A*)obj;
 *std::cout << a->inumber << std::endl;
 *
 *调用成员函数
 *std::string funcName = "test";
 *obj->call<void>(funcName);
 *
 */
namespace  ClassReflectionTool {




    /**
     * 函数后缀名工具类
     */
    class FuncSuffixTool {
    private:
        FuncSuffixTool() = default;
        ~FuncSuffixTool() = default;


        template<typename T>
        static void getTypeStr(std::string& str) {

            str += "_"+std::string(typeid(T).name());

        }


    public:
        /**
         * 获取成员函数后缀名
         * @tparam ARGS
         * @return
         */
        template<typename... ARGS>
        static const std::string getClassFuncSuffixStr() {

            std::string classFuncSuffixStr;

           std::initializer_list<int> dummy = {(FuncSuffixTool::getTypeStr<ARGS>(classFuncSuffixStr),0)...};
            (void)dummy;  // 避免未使用变量警告

            return classFuncSuffixStr;

        }

    };


    /**
     * 类参数数据类
     */
    class ClassField{
    private:
        std::string m_name;
        std::string m_type;
        size_t m_offset;

    public:
        ClassField(){
            this->m_name = "";
            this->m_type = "";
            this->m_offset = 0;
        }

        /**
         *
         * @param name
         * @param type
         * @param offset
         */
        ClassField(const std::string& name, const std::string& type, size_t offset){
            this->m_name = name;
            this->m_type = type;
            this->m_offset = offset;
        }

        ~ClassField() = default;

        /**
         *
         * @return
         */
        std::string getName(){
            return this->m_name;
        }

        /**
         *
         * @return
         */
        std::string  getType(){
            return this->m_type;
        }

        /**
         *
         * @return
         */
        size_t getOffset(){
            return this->m_offset;
        }

    };

/**
     * 类函数数据类
     */
    class ClassMethod{
    private:
        std::string m_name;
        uintptr_t m_method;

    public:

        ClassMethod(){
            this->m_name = "";
            this->m_method = 0;
        }

        /**
         *
         * @param name
         * @param method
         */
        ClassMethod(const std::string& name, uintptr_t method){


            this->m_name = name;
            this->m_method = method;


        }


        ~ClassMethod() =default;




        /**
         *
         * @return
         */
        const std::string& getName(){
            return this->m_name;
        }

        /**
         *
         * @return
         */
        uintptr_t getMethod(){

            return this->m_method;
        }
    };


    template<typename CLASS_TYPE>
    class Object {

    private:
        CLASS_TYPE m_type;

    public:
        //类类型类型的值，通过Decltype获取CLASS_TYPE
        static CLASS_TYPE decltypeValue;
    public:
        Object() = default;

        virtual ~Object() = default;

        /**
         *
         * @return
         */
        virtual CLASS_TYPE getType() const{
            return this->m_type;
        }

        /**
         * 设置类参数
         * @tparam T
         * @param fieldName
         * @param value
         */
        template<typename T>
        void set(const std::string& fieldName, const T& value);


        /**
         * 设置类参数
         * @param fieldName
         * @param value
         */
        void set(const std::string& fieldName, const char* value);


        /**
         * 调用类函数
         * @tparam R
         * @tparam Args
         * @param methodName
         * @param args
         * @return
         */
        template<typename R, typename ...Args>
        R call(const std::string& methodName, Args... args );

    };

    //创建对象的函数指针
    template<typename CLASS_TYPE>
    using create_object = Object<CLASS_TYPE>*(*)();

    template<typename CLASS_TYPE>
    class ClassFactory {
    private:
        std::unordered_map<CLASS_TYPE,create_object<CLASS_TYPE>> m_classMap;
        std::unordered_map<CLASS_TYPE,std::unordered_map<std::string,ClassField*>> m_classFieldsMap;
        std::unordered_map<CLASS_TYPE,std::unordered_map<std::string,ClassMethod*>> m_classMethodsMap;

        //已经注册的类类型
        std::unordered_set<CLASS_TYPE> m_classTypes;

        //已经注册的类成员变量名
        std::unordered_set<std::string> m_classFieldNames;

        //已经注册的类成员函数名
        std::unordered_set<std::string> m_classMethodNames;

        //单例锁
        static std::mutex singletonMutex;

        //单例
        static ClassFactory* singletonFactory;

    public:
        /**
         * 友元类设置
         */
        friend class Object<CLASS_TYPE>;

        friend class ClassRegister;

    private:
        /**
         * 私有化构造函数
         */
        ClassFactory() = default;

        /**
         * 私有化析构函数
         */
        ~ClassFactory() = default;



        /**
         * 注册类
         * @param type
         * @param method
         */
        void registerClass(const CLASS_TYPE& type, create_object<CLASS_TYPE> method){
            this->m_classMap[type] = method;

            //登记已经注册的类类型
            this->m_classTypes.insert(type);
        }





        /**
         *
         * @param type
         * @param fieldName
         * @param fieldType
         * @param offset
         */
        void registerClassField(const CLASS_TYPE& type, const std::string& fieldName, const std::string& fieldType, size_t offset ){
            this->m_classFieldsMap[type][fieldName] = new ClassField(fieldName,fieldType,offset);

            //登记已经注册的类成员变量名
            this->m_classFieldNames.insert(fieldName);
        }

        /**
         *
         * @param type
         * @param fieldName
         * @return
         */
        ClassField* getClassField(const CLASS_TYPE& type,const std::string& fieldName){
            if(this->m_classFieldsMap.count(type) < 1) return nullptr;

            if(this->m_classFieldsMap[type].count(fieldName) < 1) return nullptr;

            return this->m_classFieldsMap[type][fieldName];
        }


        /**
         *
         * @param classType
         * @param mothedSerialNumber
         * @param methodPionter
         */
        void registerClassMethod(const CLASS_TYPE& classType, const std::string& mothedSerialNumber, uintptr_t methodPionter){

            this->m_classMethodsMap[classType][mothedSerialNumber] = new ClassMethod(mothedSerialNumber,methodPionter);

            //登记已经注册的类成员函数名
            this->m_classTypes.insert(mothedSerialNumber);
        }


        /**
         *
         * @param method
         * @return
         */
        ClassMethod* getClassMothded(const CLASS_TYPE& classType ,const std::string& methodName){


            if (this->m_classMethodsMap.count(classType) < 1) return nullptr;
            if (this->m_classMethodsMap[classType].count(methodName) < 1) return nullptr;
            return this->m_classMethodsMap[classType][methodName];

        }

    public:
        /**
         * @return
         */
        std::unordered_set<CLASS_TYPE>& getClassTypes() {
            return this->m_classTypes;
        }

        /**
         * @return
         */
        std::unordered_set<std::string>& getClassFieldNames() {
            return this->m_classFieldNames;
        }

        /**
         *
         * @return
         */
        std::unordered_set<std::string>& getClassMethodNames() {
            return this->m_classMethodNames;
        }


        /**
         * 创建类
         * @param type
         * @return
         */
        Object<CLASS_TYPE>* createClass(const CLASS_TYPE& type){
            typename std::unordered_map<CLASS_TYPE,create_object<CLASS_TYPE>>::iterator  it = this->m_classMap.begin();
            if (it == this->m_classMap.end()) return nullptr;
            return it->second();
        }


        /**
         * 获取单列
         * @return
         */
        static ClassFactory* getSingleton(){
            if(ClassFactory::singletonFactory != nullptr) return ClassFactory::singletonFactory;
            std::unique_lock<std::mutex> lock(ClassFactory::singletonMutex);
            if(ClassFactory::singletonFactory == nullptr) ClassFactory::singletonFactory = new ClassFactory();

            return ClassFactory::singletonFactory;
        }

    };




    /**
       * 注册功能类
       */
    class ClassRegister{

    public:

        template<typename CLASS_TYPE>
        ClassRegister(const CLASS_TYPE& type) {
            ClassFactory<CLASS_TYPE>* singletonFactory = ClassFactory<CLASS_TYPE>::getSingleton();
        }
        /**
         *注册类
         * @tparam CLASS_TYPE
         * @param classType
         * @param method
         */
        template<typename CLASS_TYPE>
        ClassRegister(const CLASS_TYPE& classType,create_object<CLASS_TYPE> method){
            ClassFactory<CLASS_TYPE>* singletonFactory = ClassFactory<CLASS_TYPE>::getSingleton();
            singletonFactory->registerClass(classType,method);

        }


        /**
         * 注册类成员变量
         * @tparam CLASS_TYPE
         * @param classType
         * @param fieldName
         * @param fieldType
         * @param offset
         */
        template<typename CLASS_TYPE>
        ClassRegister(const CLASS_TYPE& classType, const std::string& fieldName, const std::string& fieldType, uintptr_t offset){

            ClassFactory<CLASS_TYPE>* singletonFactory = ClassFactory<CLASS_TYPE>::getSingleton();
            singletonFactory->registerClassField(classType,fieldName,fieldType,offset);

        }


        /**
         * 注册类成员函数
         * @tparam CLASS_TYPE
         * @param classType
         * @param methodName
         * @param methodPiont
         */
        template<typename CLASS_TYPE>
        ClassRegister(const CLASS_TYPE& classType , const std::string& methodName, uintptr_t methodPiont){

            ClassFactory<CLASS_TYPE>* singletonFactory = ClassFactory<CLASS_TYPE>::getSingleton();
            singletonFactory->registerClassMethod(classType,methodName,methodPiont);


        }


        ~ClassRegister() = default;
    };


};



template<typename CLASS_TYPE>
std::mutex ClassReflectionTool::ClassFactory<CLASS_TYPE>::singletonMutex;

//类类型类型的值，通过Decltype获取CLASS_TYPE
template<typename CLASS_TYPE>
CLASS_TYPE ClassReflectionTool::Object<CLASS_TYPE>::decltypeValue;


template<typename CLASS_TYPE>
typename ClassReflectionTool::ClassFactory<CLASS_TYPE>* ClassReflectionTool::ClassFactory<CLASS_TYPE>::singletonFactory = nullptr;


/**
 *设置成员变量
 * @tparam T
 * @param fieldName
 * @param value
 */
template<typename CLASS_TYPE>
template<typename T>
void ClassReflectionTool::Object<CLASS_TYPE>::set(const std::string &fieldName, const T& value) {

    typename ClassReflectionTool::ClassFactory<CLASS_TYPE>* singletonFactory = ClassReflectionTool::ClassFactory<CLASS_TYPE>::getSingleton();
    ClassReflectionTool::ClassField* field = singletonFactory->getClassField(this->getType(),fieldName);

    if(field == nullptr) return;

    //生成地址参数
    T* fieldPionter = reinterpret_cast<T*>(reinterpret_cast<char*>(this)+field->getOffset());

    //参数赋值
    *fieldPionter = value;

}



/**
 * 设置成员变量（const char*类型独占）
 * @tparam CLASS_TYPE
 * @param fieldName
 * @param value
 */
template<typename CLASS_TYPE>
void ClassReflectionTool::Object<CLASS_TYPE>::set(const std::string &fieldName, const char* value) {

    typename ClassReflectionTool::ClassFactory<CLASS_TYPE>* singletonFactory = ClassReflectionTool::ClassFactory<CLASS_TYPE>::getSingleton();
    ClassReflectionTool::ClassField* field = singletonFactory->getClassField(this->getType(),fieldName);

    if(field == nullptr) return;

    //生成地址参数
    std::string* fieldPionter = reinterpret_cast<std::string*>(reinterpret_cast<char*>(this)+field->getOffset());


    //参数赋值
    *fieldPionter = value;

}
/**
 * 调用类成员函数
 * @param methodName
 * @param args
 * @return
 */
template<typename CLASS_TYPE>
template<typename R, typename ...Args>
R ClassReflectionTool::Object<CLASS_TYPE>::call(const std::string &methodName, Args ...args) {

    ClassReflectionTool::ClassFactory<CLASS_TYPE>*  singletonFactory = ClassReflectionTool::ClassFactory<CLASS_TYPE>::getSingleton();

    //生成函数序列名
    std::string mothedSignatureStr =
        methodName+ClassReflectionTool::FuncSuffixTool::getClassFuncSuffixStr<R,Args...>();

    typename ClassReflectionTool::ClassMethod* methodData = singletonFactory->getClassMothded(this->getType(),mothedSignatureStr);

    if(methodData == nullptr) throw std::runtime_error("未找到成员函数"+methodName);

    uintptr_t  mothedPionter =methodData->getMethod();

    typedef std::function<R(decltype(this),Args...)> classMethod;

    //(*((classMethod*)methodData))(this,args...)*/
    return  (*((classMethod*)mothedPionter))(this,args...);

}

/*#define AUTHORIZATION_CLASS_REFLECTION_PERMISSION(className)\
    public:\
    friend void REGISTER_CLASS(const char*);\*/


class TTT {
public:
    /**
 * 注册类宏定义
 * @param className
 */
#define REGISTER_CLASS(className)\
ClassReflectionTool::Object<decltype(className::decltypeValue)>* createObject##className(){ \
return new className();\
}\
ClassReflectionTool::ClassRegister classRegister##className##className( \
className().getType(),                  \
createObject##className)\

};

/**
 * 注册类宏定义
 * @param className
 */
/*
#define REGISTER_CLASS(className)\
    ClassReflectionTool::Object<decltype(className::decltypeValue)>* createObject##className(){ \
        return new className();\
    }\
    ClassReflectionTool::ClassRegister classRegister##className##className( \
    className().getType(),                  \
    createObject##className)\
    */

/**
 * 注册类参数宏定义
 * (size_t)(&(className##fieldName.fieldName)) - (size_t)(&className##fieldName)
 * @param className
 * @param fieldName
 * @param fieldType
 */
#define REGISTER_CLASS_FIELD(className,fieldName,fieldType)\
    size_t get##className##fieldName##FieldOffset() {       \
    return (size_t)(&(className##fieldName.fieldName)) - (size_t)(&className##fieldName)\
    }\
    className className##fieldName;                          \
    ClassReflectionTool::ClassRegister classRegister##className##fieldName( \
    className##fieldName.getType(),                                    \
    #fieldName,#fieldType,                                             \
    get##className##fieldName##FieldOffset())\


/**
 * 注册类方法宏定义
 * @param className
 * @param methodName
 * @param returnType
 */
#define REGISTER_CLASS_METHOD(className,methodName,returnType,...) \
    uintptr_t get##className##methodName##Address(){    \
    return (uintptr_t)&(className##methodName##method);     \
    }\
    std::string className##methodName =                             \
       #methodName+ClassReflectionTool::FuncSuffixTool::getClassFuncSuffixStr<returnType, ##__VA_ARGS__>();  \
    std::function<returnType(className*,##__VA_ARGS__)> className##methodName##method = &className::methodName; \
    ClassReflectionTool::ClassRegister classRegister##className##methodName(   \
        className().getType(), \
        className##methodName,  \
        get##className##methodName##Address());  \

